package stone926.mods.more_enchantments.enchantments.legendary;

import net.minecraft.enchantment.EnchantmentTarget;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityGroup;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.AxeItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.TridentItem;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.Box;
import net.minecraft.world.World;
import stone926.mods.more_enchantments.damage.StoneEntityDamageSource;
import stone926.mods.more_enchantments.util.RandomUtil;

public class ExtinctionEnchantment extends AbstractLegendaryEnchantment {

  public ExtinctionEnchantment() {
    super(EnchantmentTarget.WEAPON, new EquipmentSlot[]{EquipmentSlot.MAINHAND});
  }

  public static int getXpCost(int lvl) {
    return lvl * 5;
  }

  public static int getExtinctRadius(int lvl, LivingEntity user) {
    if (user instanceof PlayerEntity p) {
      int xpCost = getXpCost(lvl);
      if (p.totalExperience > xpCost) p.addExperience(-xpCost);
    }
    int x = 9;
    StatusEffectInstance weak = user.getStatusEffect(StatusEffects.WEAKNESS);
    StatusEffectInstance blind = user.getStatusEffect(StatusEffects.BLINDNESS);
    if (weak != null) x = Math.max(1, x - weak.getAmplifier());
    x *= lvl;
    if (blind != null) x = Math.max(0, x - blind.getAmplifier() + 1);
    return x;
  }

  public static int getExtinctYRadius(int lvl, LivingEntity user) {
    return lvl * 20;
  }

  @Override
  public boolean isAcceptableItem(ItemStack stack) {
    return super.isAcceptableItem(stack) || stack.getItem() instanceof AxeItem || stack.getItem() instanceof TridentItem;
  }

  @Override
  public int getMaxLevel() {
    return 3;
  }

  @Override
  public void onTargetDamaged(LivingEntity user, Entity target, int level) {
    super.onTargetDamaged(user, target, level);
    World world = user.getEntityWorld();
    if (!world.isClient && !target.isAlive() && !target.isPlayer()) {
      ServerWorld serverWorld = (ServerWorld) world;
      world.getEntitiesByType(target.getType(), Box.from(target.getPos()).expand(
                                getExtinctRadius(level, user),
                                getExtinctYRadius(level, user),
                                getExtinctRadius(level, user)
                              ), EntityPredicates.VALID_ENTITY
      ).stream().filter(e -> e != target).forEach((entity -> {
        if (entity.damage(StoneEntityDamageSource.extinction(user), Integer.MAX_VALUE)) {
          serverWorld.spawnParticles(
            ParticleTypes.SWEEP_ATTACK,
            entity.getX(), entity.getY() + entity.getEyeHeight(entity.getPose()), entity.getZ(),
            RandomUtil.nextInt(1, 5, user.getRandom()), 0, 0.2, 0, 0
          );
          if (user instanceof PlayerEntity player) {
            if (player.totalExperience > 2)
              player.addExperience(-2);
            player.addExhaustion(0.3F);
          }
        }
      }));
    }
  }

  @Override
  public float getAttackDamage(int level, EntityGroup group) {
    return level;
  }

}
